# -*- coding: utf-8 -*-

import urllib2, urllib, re
import hurryoff.log as log
from hurryoff.db import *
from os import path
import subprocess

TrainInfo_URL = "http://uz.gov.ua/index.php?m=services.transppl.ScheduleOra&f=ScheduleOra.Prom&lng=uk"
SubtrainInfo_URL = "http://uz.gov.ua/index.php?m=services.transppl.ScheduleOra&f=ScheduleOra.Train&lng=uk"
TrainParam = "otpr1"
SubtrainParam = "T1"

class UzTrainsSpider:

    _subTrainsPattern = ".*(<select.*?name=\"T1\".*>.*<option.*</select>).*"
    _subTrainsNumberPattern = r"<option.*?value\s*=\s*[\"']?((?:.(?![\"']?\s+(?:\S+)=|[>\"']))+.)[\"']?"
    _subTrainsNumbers = re.compile(_subTrainsNumberPattern, re.DOTALL)
    _trainInfoContentPattern = ".*(<h1>Інформація по номеру поїзда</h1>(.*?</table>){6}).*"

    _parseFileTpl = path.join(path.dirname(__file__), "train.parse.js.template")
    _parseFile = path.join(path.dirname(__file__), "train.parse.js")
    _rhinoJS = path.abspath(path.join(path.dirname(__file__), "..", "..", "libs", "env.rhino.js"))
    _rhinoLib = path.join(path.dirname(__file__), "..", "..", "libs", "rhino", "js.jar")

    def __init__(self, echo=None):
        self._logger = log.instance_logger(self, echoflag=echo)

    def __sedReplace(self, pattern, fromFile, toFile=None):
        params = ["sed", "-i", pattern, fromFile]
        out = subprocess.PIPE
        if toFile:
            params.remove("-i")
            out = open(toFile, "w")
        subprocess.Popen(params, stdout=out).wait()

    def __runTrainParsing(self, rawDataId):
        self.__sedReplace("s/#train_raw_id#/%s/" % rawDataId, self._parseFileTpl, toFile=self._parseFile)
        self.__sedReplace("s/#RhinoJS#/%s/" % self._rhinoJS.replace('/', '\/'), self._parseFile)
        proc = subprocess.Popen(["java", "-jar", self._rhinoLib, "-opt", "-1", self._parseFile], stdout=subprocess.PIPE)
        out, err = proc.communicate()
        if err or ('Success' not in out):
            raise UzParsingException(err, out)

    def __getSubTrain(self, trainNumber):
        self._logger.info("Get subtrain by internal number : %s" % trainNumber)
        request = urllib2.Request(SubtrainInfo_URL, data=urllib.urlencode({ SubtrainParam : trainNumber }))
        response = urllib2.urlopen(request)
        rawData = RawData(readData(response, pattern=self._trainInfoContentPattern, chunk_size=32768))

        session = getSession()
        with session.begin(subtransactions=True):
            session.add(rawData)
        self._logger.info("Raw Data saved with id = %s" % rawData.id)

        try:
            self.__runTrainParsing(rawData.id)
        except:
            with getSession().begin(subtransactions=True):
                session.delete(rawData)
            raise

    def processTrain(self, globalNumber):
        self._logger.info("Get train by number : %s" % globalNumber)
        request = urllib2.Request(TrainInfo_URL, data=urllib.urlencode({ TrainParam : globalNumber }))
        response = urllib2.urlopen(request)
        for subNumber in self._subTrainsNumbers.findall(readData(response, pattern=self._subTrainsPattern)):
            self.__getSubTrain(subNumber)

def convert(data, initialEncoding, returnEncoding):
    return unicode(data, initialEncoding).encode(returnEncoding)

def readData(response, pattern=None, returnEncoding="utf-8", chunk_size=16384):
    encoding = response.headers["content-type"].split("charset=")[-1]

    if not pattern:
        return convert(response.read(), encoding, returnEncoding)

    compiled = re.compile(pattern, flags=re.DOTALL)
    data = ""
    while 1:
        chunk = convert(response.read(chunk_size), encoding, returnEncoding)
        if not chunk:
            return data
        data += chunk
        if compiled.match(data):
            return compiled.sub(r"\1", data)

class UzParsingException(Exception):

    def __init__(self, errorMsg=None, warningMsg=None):
        self.errorMsg = errorMsg
        self.warningMsg = warningMsg